package at.ac.tuwien.ir.controller;
import weka.core.Instances;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.zip.GZIPInputStream;

import at.ac.tuwien.ir.model.DocumentSimilarity;

public class SimilarityController implements ISimilarityController{
	private ArrayList<String> topics = new ArrayList<String>();
	private Instances data;

	public SimilarityController()
	{
		topics.add("misc.forsale/76057");
		topics.add("talk.religion.misc/83561");
		topics.add("talk.politics.mideast/75422");
		topics.add("sci.electronics/53720");
		topics.add("sci.crypt/15725");
		topics.add("misc.forsale/76165");
		topics.add("talk.politics.mideast/76261");
		topics.add("alt.atheism/53358");
		topics.add("sci.electronics/54340");
		topics.add("rec.motorcycles/104389");
		topics.add("talk.politics.guns/54328");
		topics.add("misc.forsale/76468");
		topics.add("sci.crypt/15469");
		topics.add("rec.sport.hockey/54171");
		topics.add("talk.religion.misc/84177");
		topics.add("rec.motorcycles/104727");
		topics.add("comp.sys.mac.hardware/52165");
		topics.add("sci.crypt/15379");
		topics.add("sci.space/60779");
		topics.add("sci.med/59456");
	}
	public void generateSimilarityFile(String indexPath, String resultPath)
	{
		String fileSizeName;
		if (indexPath.indexOf("_") > 0)
		{
			fileSizeName = indexPath.substring(indexPath.indexOf("_") + 1, indexPath.length());
			fileSizeName = fileSizeName.substring(0, fileSizeName.indexOf("."));
		}
		else
			fileSizeName = "Large";
		
		BufferedReader reader;
		try {
			InputStream fileStream = new FileInputStream(indexPath);
			
			if (indexPath.endsWith(".gzip"))
			{
				InputStream gzipStream = new GZIPInputStream(fileStream);
				reader = new BufferedReader(new InputStreamReader(gzipStream));
			}
			else
				reader = new BufferedReader(new InputStreamReader(fileStream));

			data = new Instances(reader);
			reader.close();
			for (int i = 0; i < topics.size(); i++)
			{
				System.out.println("writing " + resultPath + fileSizeName + "_topic" + String.valueOf(i + 1) + "_groupO.txt");
				DocumentSimilarity[] topSimilarities = CalculateTopTenSimilarity(topics.get(i));
				FileWriter fileWriter = new FileWriter(resultPath + fileSizeName + "_topic" + String.valueOf(i + 1) + "_groupO.txt");
				PrintWriter writer = new PrintWriter(fileWriter);
				for (int j = 0; j < topSimilarities.length; j++)
					writer.println("topic" + String.valueOf(i + 1) + " Q0 " + topSimilarities[j].get_documentName() + " " + String.valueOf(j + 1) + " " + String.valueOf(((double)Math.round(topSimilarities[j].get_similarity() * 100))/100) + " groupO_" + fileSizeName);
				writer.close();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	private DocumentSimilarity[] CalculateTopTenSimilarity(String instanceName)
	{
		DocumentSimilarity[] similarities = new DocumentSimilarity[10];
		for (int i = 0; i < 10; i++)
			similarities[i] = new DocumentSimilarity("", 0);
		
		int instanceIndex = -1;
		
		String[] instanceNames = instanceName.split("/");
		for (int i = 0; i < data.numInstances(); i++)
		{
			if (data.instance(i).toString(0).compareTo(instanceNames[0]) == 0)
			{
				if (data.instance(i).toString(1).compareTo(instanceNames[1]) == 0)
				{
					instanceIndex = i;
					break;
				}
			}
			else
				i = i + 399;
		}	
		
		if (instanceIndex != -1)
		{
			for (int i = 0; i < data.numInstances(); i++)
			{
				if (i != instanceIndex)
				{
					double similarity = 0;
					for (int j = 2; j < data.instance(instanceIndex).numValues(); j++)
					{
						int index = data.instance(instanceIndex).attributeSparse(j).index();
						if (data.instance(i).toString(index).compareTo("0") != 0) 
							similarity += Double.parseDouble(data.instance(i).toString(index)) * Double.parseDouble(data.instance(instanceIndex).toString(index));
					}
					
					//comparing with top ten
					for (int j = 9; j >= 0; j--)
					{
						if (similarities[j].get_similarity() <= similarity)
						{
							if ((j == 0) || (similarities[j - 1].get_similarity() > similarity))
							{
								for (int k = 9; k >= j + 1; k--)
								{
									similarities[k].set_similarity(similarities[k - 1].get_similarity());
									similarities[k].set_documentName(similarities[k - 1].get_documentName());
								}
								similarities[j].set_similarity(similarity);
								similarities[j].set_documentName(data.instance(i).toString(0) + "/" + data.instance(i).toString(1));
								break;
							}
						}
						else
							break;
					}
				}
			}
		}
		return similarities;
	}
}
